#include"data.hpp"
#include"httplib.h"

namespace aod
{
#define WWW_ROOT "./www"
#define VIDEO_ROOT "/video/"
#define IMAGE_ROOT "/image/"
    TableVideo *tb_video = NULL;
    class Server
    {
    public:
        Server(int port): _port(port)
        {}

        bool RunModule()
        {
            //1.初始化数据管理模块,创建指定的目录
            tb_video = new TableVideo();
            FileUtil(WWW_ROOT).CreateDirectory();
            std::string video_real_path = std::string(WWW_ROOT) + VIDEO_ROOT;
            FileUtil(video_real_path).CreateDirectory();
            std::string image_real_path = std::string(WWW_ROOT) + IMAGE_ROOT;
            //2.搭建http服务器
            //a.设置静态资源根目录
            _srv.set_mount_point("/", WWW_ROOT);
            //b.添加请求与处理函数的映射管理
            _srv.Post("/add", Insert);
            _srv.Delete("/video/(\\d+)", Delete);
            _srv.Put("/video/(\\d+)", Update);
            _srv.Get("/video/(\\d+)", GetOne);
            _srv.Get("/video", GetAll);
            //c.启动
            _srv.listen("0.0.0.0", _port);

            return true;
        }

    private:
        int _port;
        httplib::Server _srv;
    
    private:
        // 这里需要定义成一个静态成员函数
        // 静态成员函数的参数不包括this指针，确保这个函数只有两个参数
        static void Insert(const httplib::Request &req, httplib::Response &rsp)
        {
            if(req.has_file("name") == false || 
                req.has_file("info") == false ||
                req.has_file("video") == false ||
                req.has_file("image") == false
                )
            {
                rsp.status = 400;
                rsp.body = R"({"result":false, "reason":"上传的数据信息错误"})";
                rsp.set_header("Content-type", "application/json");                    
            }

            httplib::MultipartFormData name = req.get_file_value("name");
            httplib::MultipartFormData info = req.get_file_value("info");
            httplib::MultipartFormData video = req.get_file_value("video");
            httplib::MultipartFormData image = req.get_file_value("image");

            std::string video_name = name.content;
            std::string video_info = info.content;
            std::string video_path = std::string(WWW_ROOT) + VIDEO_ROOT + video_name + video.filename;
            std::string image_path = std::string(WWW_ROOT) + IMAGE_ROOT + video_name + image.filename;

            if((FileUtil(video_path).WriteContent(video.content)) == false)
            {
                rsp.status = 500;
                rsp.body = R"({"result":false, "reason":"视频文件存储失败"})";
                rsp.set_header("Content-type", "application/json");
            }

            if((FileUtil(image_path).WriteContent(image.content)) == false)
            {
                rsp.status = 500;
                rsp.body = R"({"result":false, "reason":"图片文件存储失败"})";
                rsp.set_header("Content-type", "application/json");                
            }

            Json::Value video_json;
            video_json["name"] = video_name;
            video_json["info"] = video_info;
            video_json["video"] = VIDEO_ROOT + video_name + video.filename;
            video_json["image"] = IMAGE_ROOT + video_name + image.filename;
            if((tb_video->Insert(video_json)) == false)
            {
                rsp.status = 500;
                rsp.body = R"({"result":false, "reason":"新增数据失败"})";
                rsp.set_header("Content-type", "application/json");       
                return ;         
            }
            rsp.set_redirect("/index.html", 303);
            return ;
        }

        static void Update(const httplib::Request &req, httplib::Response &rsp)
        {
            //1.获取需要修改的视频id以及修改后的信息
            int video_id = std::stoi(req.matches[1]);
            Json::Value video;
            if((JsonUtil::Unserialize(req.body, &video)) == false)
            {
                rsp.body = R"({"result":false, "reason":"上传的信息解析失败"})";
                rsp.set_header("Content-type", "application/json");  
                return ;
            }
            if((tb_video->Update(video_id, video)) == false)
            {
                rsp.status = 500;
                rsp.body = R"({"result":false, "reason":"修改数据库信息失败"})";
                rsp.set_header("Content-type", "application/json");      
                return ;          
            }              

        }
        static void Delete(const httplib::Request &req, httplib::Response &rsp)
        {
            //1.获取要删除的视频id
            int video_id = std::stoi(req.matches[1]);
            //2.删除视频以及封面文件
            Json::Value video;
            if((tb_video->SelectOne(video_id, &video)) == false)
            {
                rsp.body = R"({"result":false, "reason":"不存在视频信息"})";
                rsp.set_header("Content-type", "application/json");  
                return ;
            }
            
            std::string video_path = WWW_ROOT + video["video"].asString();
            std::string image_path = WWW_ROOT + video["image"].asString();
            remove(video_path.c_str());
            remove(image_path.c_str());
            //3.删除数据库信息
            if((tb_video->Delete(video_id)) == false)
            {
                rsp.status = 500;
                rsp.body = R"({"result":false, "reason":"删除数据库信息失败"})";
                rsp.set_header("Content-type", "application/json");      
                return ;          
            }            
            return ;
        }

        static void GetOne(const httplib::Request &req, httplib::Response &rsp)
        {
            //1.获取视频id
            int video_id = std::stoi(req.matches[1]);
            //2.在数据库中查询视频信息即可
            Json::Value video;
            if((tb_video->SelectOne(video_id, &video)) == false)
            {
                rsp.status = 500;
                rsp.body = R"({"result":false, "reason":"查询视频信息失败"})";
                rsp.set_header("Content-type", "application/json");      
                return ;                    
            }
            //3.组织响应正文
            JsonUtil::Serialize(video, &rsp.body);
            rsp.set_header("Content-Type", "application/json");
            return ;
        }

        static void GetAll(const httplib::Request &req, httplib::Response &rsp)
        {
            //查询所有需要考虑是否是模糊匹配还是就真的是一个查询所有
            bool select_flage = true; // 默认查询所有
            std::string search_key;
            if(req.has_param("search") == true)
            {
                // 模糊匹配
                select_flage = false;
                search_key = req.get_param_value("search");
            }
            Json::Value videos;
            if(select_flage == true)
            {
                if(tb_video->SelectAll(&videos) == false)
                {
                    rsp.status = 500;
                    rsp.body = R"({"result":false, "reason":"查询数据库中所有信息失败"})";
                    rsp.set_header("Content-type", "application/json");      
                    return ;                              
                }
            }
            else
            {
                if (tb_video->SelectLike(search_key, &videos) == false)
                {
                    rsp.status = 500;
                    rsp.body = R"({"result":false, "reason":"查询匹配的数据库信息失败"})";
                    rsp.set_header("Content-type", "application/json");
                    return;
                }
            }
            JsonUtil::Serialize(videos, &rsp.body);
            rsp.set_header("Content-Type", "application/json");

            return ;
        }
    };
}

